/* 
    module：axios 数据交互模块
*/
import axios, { AxiosInstance } from 'axios';
import { useQueueStore } from 'store/useUsers';
const useQueueUrl = useQueueStore();
/**
 * @class 发送请求
 * @description 通过 axios 向服务器发送请求,请求前拦截请求，返回后拦截响应，
 * @param {undefined} null - 无
 * @return {function,function} get, post 请求
 * @example
 *   new class()
 */
class Request {
    readonly baseUrl: string;
    timeout: number;
    queue: {};
    state: any;
    constructor() {
        this.baseUrl = import.meta.env.VITE_API_URL;
        this.timeout = 30000;
        this.queue = {};
        this.state = {
            '200': (data: any) => data,
            '201': (data: any) => console.warn(data),
            '400': (data: any) => console.warn('请求失败！请您稍后重试', data),
            '401': (data: any) => console.warn('登录失效！请您重新登录', data),
            '403': (data: any) => console.warn('当前账号无权限访问！', data),
            '404': (data: any) => console.warn('你所访问的资源不存在！', data),
            '405': (data: any) => console.warn('请求方式错误！请您稍后重试！', data),
            '408': (data: any) => console.warn('请求超时！请您稍后重试！', data),
            '500': (data: any) => console.warn('服务异常！', data),
            '502': (data: any) => console.warn('网关错误！', data),
            '503': (data: any) => console.warn('服务不可用！', data),
            '504': (data: any) => console.warn('网关超时！', data)
        };
    }
    private setInterceptor(instance: AxiosInstance, url: string) {
        instance.interceptors.request.use((config: any) => {
            // Object.keys((this.queue as any)).length || //开启loading
            //config.headers['X-Access-Token'] = token //设置请求头
            //config.headers['Content-Type'] = application/json //设置请求头
            const CancelToken = axios.CancelToken;
            if ((this.queue as any)[url]) (this.queue as any)[url](); //当前请求未完成再次发起，取消上一次请求，发起新的请求
            config.cancelToken = new CancelToken((c) => {
                (this.queue as any)[url] = c;
            });
            //  将(this.queue as any)存到 pinia 中，路由切换时清空并取消请求；也可以通过url取消某个请求，
            useQueueUrl.setUsers(this.queue as any);
            return config;
        });
        instance.interceptors.response.use(
            ({ data }) => {
                delete (this.queue as any)[url];
                //Object.keys((this.queue as any)).length || //关闭loading
                return this.state[data.code] ? this.state[data.code](data.data) : Promise.reject(data); //判断状态
            },
            (err: any) => {
                delete (this.queue as any)[url];
                //Object.keys((this.queue as any)).length || //关闭loading
                return Promise.reject(err);
            }
        );
    }
    private request(options: { url: string; method: string; params: {} | null; data?: {} }) {
        let instance = axios.create();
        let config = {
            baseURL: this.baseUrl,
            timeout: this.timeout,
            ...options
        };
        this.setInterceptor(instance, options.url);
        return instance(config);
    }
    /**
     * @function 发送请求
     * @description 通过 axios.get 向服务器发送请求
     * @param {String} url -  请求地址
     * @param {Object} params -  请求查询参数
     * @param {boolean} cancel -  当前请求如果存在，就不从新发起新的请求
     * @return {Promise} 返回接口数据
     * @example   new class().get(url)
     */
    public get(url: string, params: object = {}, cancel: boolean = false): Promise<any> {
        if (cancel && (this.queue as any)[url]) return Promise.reject();
        return this.request({
            url,
            method: 'get',
            params
        });
    }

    /**
     * @function 发送请求
     * @description 通过 axios.post 向服务器发送请求
     * @param {String} url -  请求地址
     * @param {Object} data -  请求体 body 参数
     * @param {Object} params -  请求查询参数
     * @param {boolean} cancel -  当前请求如果存在，就不从新发起新的请求
     * @return {Promise} 返回接口数据
     * @example new class().post(url)
     */
    public post(url: string, data: object = {}, cancel: boolean = false, params: object | null = null): Promise<any> {
        if (cancel && (this.queue as any)[url]) return Promise.reject();
        return this.request({
            url,
            method: 'post',
            data,
            params
        });
    }
}
export default new Request();
